import errorCodeTip from './errorCodeTip'
export default class Printer {

  constructor(watchChange = false) {
    this.status = false // 蓝牙是否打开
    this.loading = false // 是否正在搜索
    this.list = [] //发现的设备列表
    this.searchTimer = null
    this.deviceId
    this.platform = uni.getSystemInfoSync().platform
  }

  /**
   * 当蓝牙连接状态改变时
   */
  onStateChange(cb) {
    uni.onBluetoothAdapterStateChange((res) => {
      if (typeof cb == 'function') cb(res)
    })
  }

  /**
   * 打开手机蓝牙
   */
  openPhoneBluetooth(cb) {
    console.log('打开手机蓝牙')
    let main, BluetoothAdapter, BAdapter
    let platform = this.platform
    let enable = false
    let res = null
    switch (platform) {
      case 'android':
        main = plus.android.runtimeMainActivity()
        BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter")
        BAdapter = BluetoothAdapter.getDefaultAdapter()
        if (!BAdapter.isEnabled()) {
          enable = BAdapter.enable()
        }
        break;
      case 'ios':
        // main = plus.android.runtimeMainActivity()
        // BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter")
        // BAdapter = BluetoothAdapter.getDefaultAdapter()
        // if (!BAdapter.isEnabled()) {
        //   BAdapter.enable()
        // }
        break;
      default:
        break;
    }
    return enable
  }

  /**
   * 初始化蓝牙
   */
  openBluetooth(cb) {
    uni.openBluetoothAdapter({
      success: (res) => {
        this.status = true
        if (typeof cb == 'function') cb(true, res)
      },
      fail: (e) => {
        this.status = false
        if (typeof cb == 'function') cb(false, e)
        let enable = this.openPhoneBluetooth()
        if (!enable) {
          uni.showToast({
            icon: "none",
            title: "请打开手机蓝牙"
          })
        }
      }
    })
  }

  /*
   * 搜索附近的蓝牙设备
   */
  search(config = {
    search: null,
    finish: null,
  }, finishTime = 20) {
    // 检查是否开启了蓝牙，如果未开启则先开启蓝牙
    if (this.status) {
      uni.startBluetoothDevicesDiscovery({
        success: (res) => {
          // uni.onBluetoothDeviceFound(res => {
          uni.onBluetoothDeviceFound(res => {
            res.devices.forEach(item => {
              if (!this.list.some(v => v.deviceId == item.deviceId)) this.list.push(item)
            })
            if (typeof config.search == 'function') config.search(this.list)
          })
          // this.searchTimer = setTimeout(() => {
          //   if (typeof config.finish == 'function') config.finish()
          //   this.stopSearch()
          // }, 1000 * finishTime) // 30s后关闭
        }
      })
    } else {
      this.openBluetooth(() => {
        this.search(config)
      })
    }
  }

  /*
   * 停止搜索
   */
  stopSearch(cb) {
    return new Promise((resolve, reject) => {
      uni.stopBluetoothDevicesDiscovery({
        success: (res) => {
          resolve(res)
          if (typeof cb == 'function') cb(res)
        },
        fail: fail => {
          reject(fail)
        }
      })
    })

  }

  /*
   * 连接蓝牙
   */
  connect({
    deviceId
  }, cb) {
    // this.stopSearch();
    uni.createBLEConnection({
      deviceId: deviceId,
      success: (res) => {
        this.getSeviceId(deviceId, (res) => {
          if (typeof cb == 'function') {
            if (!res.state) console.log('connect success', deviceId);
            cb({
              state: !res.state ? 0 : 1,
              msg: !res.state ? "连接成功" : "获取servicId失败",
              deviceId: deviceId,
              data: res.data
            })
          }
        })
      },
      fail: (e) => {
        console.log('connect error', deviceId, e);
        if (typeof cb == 'function') cb({
          state: e.errCode,
          msg: e.errMsg,
          deviceId: deviceId
        })
      }
    })
  }

  getSeviceId(deviceId, cb) {
    uni.getBLEDeviceServices({
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId,
      success: (res) => {
        console.log('getSeviceId success', res);
        if (res.services && res.services.length > 0) {
          this.getCharacteristics(deviceId, res.services, (r) => {
            if (typeof cb == "function") cb({
              state: 0,
              data: r
            })
          })
        } else {
          console.log('getSeviceId fail', res);
          if (typeof cb == "function") cb({
            state: 1,
            data: { code: 1001, errMsg: "获取serviceId失败" }
          })
        }
      },
      fail: (e) => {
        console.log('getSeviceId fail', deviceId, e);
        if (typeof cb == "function") cb({
          state: 1,
          data: e
        })
      }
    })
  }

  getCharacteristics(deviceId, services, cb) {
    let list = []
    let obj = {
      readCharaterId: "",
      readServiceId: "",
      writeCharaterId: "",
      writeServiceId: "",
      notifyCharaterId: "",
      notifyServiceId: "",
      indicateCharaterId: "",
      indicateServiceId: ""
    }
    let num = 0
    console.log(deviceId, services)
    for (let i = 0; i < services.length; i++) {
      let item = services[i];
      uni.getBLEDeviceCharacteristics({
        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
        deviceId,
        serviceId: item.uuid,
        success(res) {
          num++
          for (let j = 0; j < res.characteristics.length; j++) {
            let ele = res.characteristics[j];
            if (ele.properties.read) {
              obj.readCharaterId = ele.uuid
              obj.readServiceId = item.uuid
            }
            if (ele.properties.write) {
              obj.writeCharaterId = ele.uuid
              obj.writeServiceId = item.uuid
            }
            if (ele.properties.notify) {
              obj.notifyCharaterId = ele.uuid
              obj.notifyServiceId = item.uuid
            }
            if (ele.properties.indicate) {
              obj.indicateCharaterId = ele.uuid
              obj.indicateServiceId = item.uuid
            }
          }
          if (num == services.length) {
            if (typeof cb == 'function') cb(obj)
          }
        },
        fail(e) {
          console.log('getCharacteristics fail', e);
          num++
          if (num == services.length) {
            if (typeof cb == 'function') cb(obj)
          }
        }
      })
    }

  }

  /**
   * 链接蓝牙设备
   * @param {*} deviceId 设备id
   */
  createBLEConnection(deviceId) {
    return new Promise((resolve, reject) => {
      uni.createBLEConnection({
        deviceId,
        success: (res) => {
          console.log("res:createBLEConnection success " + JSON.stringify(res));
          resolve(res);
        },
        fail: err => {
          console.log("res:createBLEConnection fail" + JSON.stringify(err));
          reject(err);
        }
      })
    });
  }

  /**
   * 获取servics
   * @param {*} deviceId 
   */
  async getBLEDeviceServices(deviceId) {
    return new Promise(async (resolve, reject) => {
      let getServices = () => {
        uni.getBLEDeviceServices({
          deviceId,
          success: async (res) => {
            console.log('getSeviceId success', res);
            if (res.services.length > 0) {
              console.log('getSeviceId success****', res);
              resolve(res)
            } else {
              getServices()
            }
          },
          fail: (e) => {
            reject(e)
            console.log('getSeviceId fail', deviceId, e);
          }
        })
      }
      getServices()
    })
  }

  /**
   * 获取特征值
   * @param {*} deviceId 
   * @param {*} serviceId 
   */
  getBLEDeviceCharacteristics(deviceId, serviceId) {
    return new Promise((resolve, reject) => {
      uni.getBLEDeviceCharacteristics({
        deviceId,
        serviceId,
        success: res => {
          resolve(res)
        },
        fail: err => {
          reject(err);
        }
      })
    })
  }

  /*
   * 断开连接
   */
  disconnect({
    deviceId
  }, cb) {
    uni.closeBLEConnection({
      deviceId,
      success: res => {
        if (typeof cb == 'function') cb(res)
      },
      fail: e => {
        if (typeof cb == 'function') cb(e)
      }
    })
  }

  /*
   * 查询状态
   */
  state() { }
  /**
   * 向打印机写值
   * @param {*} config 
   */
  writeBLECharacteristicValue(config) {
    return new Promise((resolve, reject) => {
      uni.writeBLECharacteristicValue({
        value: config.value,
        deviceId: config.deviceId,
        serviceId: config.serviceId,
        characteristicId: config.characteristicId,
        success: (res) => {
          resolve({ state: 0 })
          console.log('writeBLECharacteristicValue resolve');
        },
        fail: (res) => {
          console.log('writeBLECharacteristicValue reject');
          reject(res)
        },
      })
    })
  }

  notifyBLECharacteristicValueChange(config) {
    let { deviceId, serviceId, characteristicId } = config

    uni.notifyBLECharacteristicValueChange({
      state: true, // 启用 notify 功能
      deviceId,
      serviceId,
      characteristicId,
      success(res) {

      },
      fail(res) {
        console.log('notifyBLECharacteristicValueChange:' + res.errMsg);
      }
    });
  }

  /*
   * 打印小票
   * @param {number} num 打印份数
   */
  print(config, currentTime, currentPrint, failTime) {
    let {
      deviceId,
      writeServiceId,
      writeCharaterId,
      num,
      buff,
      success,
      fail,
      complete
    } = config
    let oneTimeData = 20 // 每次发送字节数量
    let printerNum = num || 1 // 打印几份
    let loopTime = parseInt(buff.length / oneTimeData) // 分包数
    let lastData = parseInt(buff.length % oneTimeData) // 最后的字节数据量
    loopTime = loopTime + 1
    currentTime = currentTime || 1 // 第几次打印
    currentPrint = currentPrint || 0 // 已经打印份数
    failTime = failTime || 0 // 打印失败的次数
    let buf = null
    let dataView = null
    if (currentTime < loopTime) {
      buf = new ArrayBuffer(oneTimeData);
      dataView = new DataView(buf);
      for (var i = 0; i < oneTimeData; ++i) {
        dataView.setUint8(i, buff[(currentTime - 1) * oneTimeData + i]);
      }
    } else {
      buf = new ArrayBuffer(lastData);
      dataView = new DataView(buf);
      for (var i = 0; i < lastData; ++i) {
        dataView.setUint8(i, buff[(currentTime - 1) * oneTimeData + i]);
      }
    }

    uni.writeBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: writeServiceId,
      characteristicId: writeCharaterId,
      value: buf,
      success: (res) => {
      },
      fail: (e) => {
        console.log('print fail e', e);
      },
      complete: (c) => {
        if (c.code) {
          failTime++
          console.log('print fail c', c);
        }
        currentTime++;
        if (currentTime <= loopTime) {
          this.print(config, currentTime, currentPrint, failTime);
        } else {
          currentPrint++;
          if (currentPrint == printerNum) {
            // 打印完成的回调
            if (failTime > 10) {
              if (typeof fail == 'function') fail({
                state: 1,
                error: e,
                errData: {
                  deviceId: deviceId,
                  serviceId: writeServiceId,
                  characteristicId: writeCharaterId,
                  value: buff,
                }
              })
            } else {
              if (typeof success == "function") success({
                state: 0,
                msg: "打印完成"
              })
            }
            if (typeof complete == 'function') complete(c)
          } else {
            currentTime = 1
            this.print(config, currentTime, currentPrint, failTime);
          }
        }
      }
    })
  }

  simplePrint(config, cb) {
    let { deviceId, writeServiceId, writeCharaterId, buff } = config
    uni.writeBLECharacteristicValue({
      deviceId: deviceId,
      serviceId: writeServiceId,
      characteristicId: writeCharaterId,
      value: buff,
      success: (res) => {
        if (typeof cb == 'function') cb({ state: 0, res })
      },
      fail: (e) => {
        if (typeof cb == 'function') cb({ state: 1, res })
      },
      complete: (c) => {

      }
    })
  }

  /*
   * 打印标签
   */
  label() { }
}
